﻿using System;
using System.IO;
using System.Reflection;
using System.Web;
using System.Xml;
using System.Xml.Serialization;

namespace HNAlbum.Logic.Entity
{
    /// <summary>
    /// Base entity class
    /// </summary>
    public abstract class EntityBase
    {
        #region Class fields
        public struct ApplicationFoler
        {
            public const string XML = "XML";
            public const string Log = "Logs";
            public const string Album = "Album";
            public const string Upload = "Temp";
        }
        protected struct ApplicationXMLFile
        {
            public const string User = "Users.xml";
            public const string Album = "Albums.xml";
        }
        /// <summary>
        /// Application physical path
        /// </summary>
        protected string AppPhysicalPath
        {
            get { return HttpContext.Current.Server.MapPath("~"); }
        }
        /// <summary>
        /// Exception messages
        /// </summary>
        protected struct HNAException
        {
            public struct Album
            {
                public const string NotFound = "Album not found.";
                public const string CannotRead = "Cannot read albums data.";
                public const string CannotCreateFolder = "Cannot create album folders. Please try again or contact us.";
                public const string CannotProcess = "Cannot process creating album. Please try again or contact us.";
            }
            public struct User
            {
                public const string CannotRead = "Cannot read users data.";
            }
        }
        #endregion

        #region Class methods
        /// <summary>
        /// Serialize the object to XML string
        /// </summary>
        /// <returns></returns>
        public string ToCleanXMLString()
        {
            //Initiate a XML serializer
            XmlSerializer x = new XmlSerializer(this.GetType());
            //Serialize this object and return the XML string
            using (StringWriter strWriter = new StringWriter())
            {
                //Create a XML writer with empty XML declaration
                using (XmlWriter xmlWriter = XmlWriter.Create(strWriter, new XmlWriterSettings() { OmitXmlDeclaration = true }))
                {
                    //Create empty namespace for a clean XML
                    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                    ns.Add("", "");
                    //Serialize it
                    x.Serialize(xmlWriter, this, ns);
                    return strWriter.ToString();
                }
            }
        }
        /// <summary>
        /// Deserialize the XML then load current instance with the data
        /// </summary>
        /// <param name="xml">XML string</param>
        public void LoadXML(string xml)
        {
            //Deserialise
            object deserialzedObj = null;
            XmlSerializer x = new XmlSerializer(this.GetType());
            StringReader reader = new StringReader(xml);
            deserialzedObj = x.Deserialize(reader);

            //Then map the properties with current class instance
            PropertyInfo[] props = this.GetType().GetProperties();
            foreach (PropertyInfo prop in props)
            {
                //Only map properties that are not marked as XML ignored
                if (!prop.IsDefined(typeof(XmlIgnoreAttribute), false))
                    prop.SetValue(this, prop.GetValue(deserialzedObj, null), null);
            }
        }
        /// <summary>
        /// Clean or create the temp upload folder
        /// </summary>
        public void CleanUploadFolder()
        {
            //Check existence
            DirectoryInfo tempDir = new DirectoryInfo(Path.Combine(AppPhysicalPath, EntityBase.ApplicationFoler.Upload));
            if (!tempDir.Exists)
            {
                //Not exist then create it
                tempDir.Create();
            }
            else
            {
                //Delete any files in the Temp folder to prepare for next new upload
                FileInfo[] files = tempDir.GetFiles();
                foreach (FileInfo file in files)
                {
                    file.Delete();
                }
            }
        }
        /// <summary>
        /// Log and throw exceptions
        /// </summary>
        /// <param name="ex"></param>
        protected void LogAndThrow(Exception ex, string message)
        {
            //TODO: Log exceptions

            throw new Exception(message);
        }
        #endregion

        #region Public methods
        /// <summary>
        /// Id string with zeros padding
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static string ToStringId(int id)
        {
            return string.Format("{0:0000}", id);
        }
        #endregion
    }
}
